package cn.wowjoy.office.data.remote;

import android.text.TextUtils;
import android.util.Log;

import com.google.gson.Gson;
import com.jakewharton.retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import com.orhanobut.logger.Logger;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.concurrent.TimeUnit;

import javax.inject.Named;
import javax.inject.Singleton;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import cn.wowjoy.office.BuildConfig;
import cn.wowjoy.office.data.local.EntitySerializer;
import cn.wowjoy.office.data.local.GsonSerializer;
import cn.wowjoy.office.utils.PreferenceManager;
import dagger.Module;
import dagger.Provides;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Created by Sherily on 2017/8/24.
 * Description: rest api module--dagger module
 */
@Module
public class RestModule {

    public RestModule() {
    }

//    private String loginUrl;
//    private String commonUrl;
//
//    public RestModule(String loginUrl, String commonUrl) {
//        this.loginUrl = loginUrl;
//        this.commonUrl = commonUrl;
//    }



    @Singleton
    @Provides
    @Named("TokenInterceptor")
    Interceptor provideTokenInterceptor(PreferenceManager preferenceManager){
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request originalRequest = chain.request();

                if (!TextUtils.isEmpty(originalRequest.header("Authorization"))) {
                    Log.e("Request0", originalRequest.url().toString());
                    return chain.proceed(originalRequest);
                }
                Request authorised = originalRequest.newBuilder()
                        .addHeader("Authorization", "Bearer " + preferenceManager.getCurrentUserAccessToken())
                        .addHeader("Connection", "close")
//                        .header("Content-Type", "application/json;charset=UTF-8")
                        .build();
                Log.e("Request1", originalRequest.url().toString());
                return chain.proceed(authorised);
            }
        };

    }

    @Singleton
    @Provides
    @Named("RetryLoggingInterceptor")
    Interceptor provideRetryLoggingInterceptor() {
        //请求成功，但没有处理

        Interceptor retryLoggingInterceptor  = new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Response response = chain.proceed(chain.request());  //如果401了，会先执行TokenAuthenticator

                Logger.e("CreateInterceptor request url "+response.request().url());
                Logger.e("CreateInterceptor  response code "+response.code());
                if (response.code() == 202) {
                    CreateInterceptorExceptioin interceptorExceptioin = new CreateInterceptorExceptioin();

                    interceptorExceptioin.setErrorCode(202);
                    interceptorExceptioin.setRetry_after(response.header("Retry-After"));
                    throw interceptorExceptioin;
                }
                return response;
            }
        };

        return retryLoggingInterceptor;
    }
    @Singleton
    @Provides
    @Named("HttpLogging")
    Interceptor provideHttpLoggingInterceptor() {
        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        return loggingInterceptor;
    }

    @Provides
    @Singleton
    @Named("NoCache")
    OkHttpClient provideOkHttpClient(@Named("TokenInterceptor")Interceptor tokenInterceptor, @Named("HttpLogging")Interceptor loggingInterceptor ,@Named("RetryLoggingInterceptor")Interceptor retryLoggingInterceptor){
        OkHttpClient.Builder unsafeOkHttpClient = getUnsafeOkHttpClient();
        return   unsafeOkHttpClient                 //new OkHttpClient.Builder()
                .connectTimeout(BuildConfig.DEFAULT_NETWORK_TIMEOUT, TimeUnit.SECONDS)
                .writeTimeout(BuildConfig.DEFAULT_NETWORK_TIMEOUT, TimeUnit.SECONDS)
                .readTimeout(BuildConfig.DEFAULT_NETWORK_TIMEOUT, TimeUnit.SECONDS)
                .retryOnConnectionFailure(false)
                .addNetworkInterceptor(retryLoggingInterceptor)
                .addNetworkInterceptor(tokenInterceptor)
                .addNetworkInterceptor(loggingInterceptor)
                .build();
    }

    @Singleton
    @Provides
    Gson provideGson() {
        return new Gson();
    }

    @Singleton
    @Provides
    @Named("GsonSerializer")
    EntitySerializer provideEntitySerializer(Gson gson) {
        return new GsonSerializer(gson);
    }

    @Singleton
    @Provides
    @Named("LoginRetrofit")
    Retrofit provideLoginRetrofit(@Named("NoCache") OkHttpClient okHttpClient, Gson gson,PreferenceManager preferenceManager){
        return new Retrofit.Builder()
                .baseUrl(preferenceManager.getLoginHost())
                .client(okHttpClient)
                .addConverterFactory(new NullOnEmptyConverterFactory())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
//         .sslSocketFactory(SSLSocketClient.getSSLSocketFactory())
//         .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
                .build();
    }
    @Singleton
    @Provides
    @Named("UpdateRetrofit")
    Retrofit provideUpdateRetrofit(@Named("NoCache") OkHttpClient okHttpClient, Gson gson,PreferenceManager preferenceManager){
        return new Retrofit.Builder()
                .baseUrl(preferenceManager.getUpdateHost())
                .client(okHttpClient)
                .addConverterFactory(new NullOnEmptyConverterFactory())
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }
    @Singleton
    @Provides
    @Named("CommonRetrofit")
    Retrofit provideCommonRetrofit(@Named("NoCache") OkHttpClient okHttpClient, Gson gson,PreferenceManager preferenceManager){
        return new Retrofit.Builder()
                .baseUrl(preferenceManager.getAPIHost())
                .client(okHttpClient)
                .addConverterFactory(GsonConverterFactory.create(gson))
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .build();
    }

    @Singleton
    @Provides
    LoginService provideLoginService(@Named("LoginRetrofit") Retrofit retrofit){
        return retrofit.create(LoginService.class);
    }

    @Singleton
    @Provides
    ApiService provideApiService(@Named("CommonRetrofit") Retrofit retrofit){
        return retrofit.create(ApiService.class);
    }
    @Singleton
    @Provides
    UpdateService provideUpdateService(@Named("UpdateRetrofit") Retrofit retrofit){
        return retrofit.create(UpdateService.class);
    }


    //信任所有证书
    private static OkHttpClient.Builder getUnsafeOkHttpClient() {
        try {
            final TrustManager[] trustAllCerts = new TrustManager[]{
                    new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) throws CertificateException {
                        }

                        @Override
                        public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                            return new java.security.cert.X509Certificate[]{};
                        }
                    }
            };

            final SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            final SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.sslSocketFactory(sslSocketFactory);
            builder.hostnameVerifier(new HostnameVerifier() {
                @Override
                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });

            return builder;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
